package com.yunkeji.config.print;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
 * @Description 打印请求信息
 *
 * @author 老张
 * @category
 * @date 2019年12月12日 下午5:50:26
 * @version V0.1
 */
@Aspect
@Component
@Slf4j
@Profile({"dev"})
public class InfoPrintDev {

    @Autowired private ObjectMapper objectMapper;

    // 使用此注解才可以进入打印
    @Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
    public void webLog() {}

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        HttpServletRequest request =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                        .getRequest();
        if (request.getRequestURI().contains("/v3/api-docs")) {
            return;
        }

        URL resource = InfoPrintDev.class.getProtectionDomain().getCodeSource().getLocation();
        String baseUrl = resource.getPath().replace("/target/classes/", "");
        String s1 = StrUtil.replaceFirst(baseUrl, "/", "");
        String replace = joinPoint.getSignature().getDeclaringTypeName().replace(".", "\\");
        File file = new File(s1 + "/src/main/java/" + replace + ".java");
        String methodName = joinPoint.getSignature().getName();
        StringBuilder result = new StringBuilder();
        int i = 1;
        try {
            BufferedReader br =
                    new BufferedReader(
                            new InputStreamReader(
                                    new FileInputStream(file),
                                    "UTF-8")); // 构造一个BufferedReader类来读取文件
            String s = null;
            while ((s = br.readLine()) != null) { // 使用readLine方法，一次读一行
                result.append(System.lineSeparator() + s);
                if (s.contains(methodName + "(")) {
                    break;
                }
                i++;
            }
            br.close();
        } catch (Exception e) {
            // e.printStackTrace();
            log.info("已经打包,未读取到源码");
        }
        log.info("------------Action Info Start------------");
        byte[] bodyBytes = ServletUtil.getBodyBytes(request);
        String str = StrUtil.str(bodyBytes, "UTF-8");
        log.info("请求参数:  ->\t ");
        if (StrUtil.isNotEmpty(str)) {
            log.info(JSONUtil.toJsonPrettyStr(str));
        }

        log.info(
                "请求方法:->\t "
                        + joinPoint.getSignature().getDeclaringTypeName()
                        + ".("
                        + joinPoint.getSignature().getDeclaringType().getSimpleName()
                        + ".java:"
                        + i
                        + ")");
        Map<String, String[]> parameterMap = request.getParameterMap();
        Set<Entry<String, String[]>> entrySet = parameterMap.entrySet();
        for (Entry<String, String[]> entry : entrySet) {
            try {
                log.info("请求参数:  ->\t " + entry.getKey() + " = " + entry.getValue()[0]);
            } catch (ArrayIndexOutOfBoundsException e) {
            }
        }
    }

    @AfterReturning(returning = "response", pointcut = "webLog()")
    public void doAfterReturning(Object response) throws Throwable {
        if (response != null) {
            try {
                log.info("响应数据:  ->\t ");
                log.info(JSONUtil.toJsonPrettyStr(objectMapper.writeValueAsString(response)));
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
        log.info("------------Action Info End------------");
    }
}
